package br.com.foxinline.servico;

import br.com.foxinline.enums.TipoLogradouro;
import br.com.foxinline.generico.ServicoGenerico;
import br.com.foxinline.modelo.Bairro;
import br.com.foxinline.modelo.Cidade;
import br.com.foxinline.modelo.Dne;
import br.com.foxinline.modelo.Endereco;
import br.com.foxinline.util.Caracter;
import java.beans.Transient;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;

/**
 *
 * @author laverson
 */
@Stateless
public class DneServico extends ServicoGenerico<Dne> {

    @EJB
    CidadeServico cityService;
    @EJB
    BairroServico bairroService;
    private Long quantidadeRegistrosResults;

    public DneServico() {
        super(Dne.class);
    }

    @Override
    public void save(Dne entity) {
        entity.setCep(Caracter.removecaracter(entity.getCep()));
        entity.setUpdateAt(new Date());
        entity.setAtivo(true);
        super.save(entity);
    }

    @Override
    public void delete(Dne entity) {
        entity.setUpdateAt(new Date());
        entity.setAtivo(false);
        update(entity);
    }

    @Override
    public void update(Dne entity) {
        entity.setCep(Caracter.removecaracter(entity.getCep()));
        entity.setUpdateAt(new Date());
        super.update(entity);
    }

    private Dne fillFilds(Dne entity) {
        entity.setCep(Caracter.removecaracter(entity.getCep()));

        entity.setNomeclog(entity.getRua());

        for (TipoLogradouro type : Arrays.asList(TipoLogradouro.values())) {
            if (entity.getRua().toLowerCase().trim().startsWith(type.getName().toLowerCase())) {
                entity.setNomeslog(entity.getRua().trim().substring(type.getName().length() + 1));
            }
        }

        return entity;
    }

    public Endereco existCep(Endereco a) {
        a.setCep(Caracter.removecaracter(a.getCep()));

        Dne dne;
        String sql = "Select d from Dne d where d.cep like lower(:cep)";

        Query query = getEntityManager().createQuery(sql);
        query.setParameter("cep", a.getCep());
        try {
            dne = (Dne) query.getResultList().get(0);

        } catch (NoResultException nr) {
            return null;
        } catch (NonUniqueResultException nre) {
            return null;
        } catch (Exception e) {
            return null;
        }

        return dne != null ? dneToEndereco(dne) : null;
    }

    private Endereco dneToEndereco(Dne dne) {
        Endereco address = new Endereco();

        address.setCep(Caracter.removecaracter(dne.getCep()));
        address.setBairro(dne.getDistrict());
        address.setLogradouro(dne.getRua());
        address.setNomeclog(dne.getNomeclog());
        address.setNomeslog(dne.getNomeslog());

        if (dne.getBairro() != null || dne.getBairro().getId() != null) {
            address.setBairroDne(dne.getBairro());
            address.setBairro(dne.getBairro().getNome());
            address.setUf(dne.getBairro().getUf());
        }

        if (dne.getCidade() != null || dne.getCidade().getId() != null) {
            if (dne.getCidade().getEstado() != null || dne.getCidade().getEstado().getId() != null) {
                address.setMunicipio(dne.getCidade().getEstado().getNome());
            }
        }

        return address;
    }

    public List<String> getAllBairro() {
        String sql = "Select distinct b.nome from Dne d JOIN d.cidade c JOIN d.bairro b where "
                + " c.id = :city";
        Query query = getEntityManager().createQuery(sql);
        query.setParameter("city", 5658);
        System.err.println((List<String>) query.getResultList());
        return (List<String>) query.getResultList();
    }

    public List<Dne> getAllUpdate(Date date) {
        System.err.println(date);
        String sql = "Select d from Dne d where d.updateAt > :update";
        Query query = getEntityManager().createQuery(sql);
        query.setParameter("update", date);

        return (List<Dne>) query.getResultList();
    }

    public List<Dne> autocomplete(String query, Bairro bairro) {
        Dne dne = new Dne();
        dne.setRua(query);

        if (bairro != null && bairro.getId() != null) {
            dne.setBairro(bairro);
        }

        return find(dne, null, null);
    }

    @Override
    public List<Dne> find(Dne dne, Integer first, Integer pageSize) {
        String select = "SELECT d ";
        String sql = "FROM " + Dne.class.getSimpleName() + " d ";
        String orderBy = " order by d.id asc";

        dne.setCep(Caracter.removecaracter(dne.getCep()));

        if (dne.getRua() != null && !dne.getRua().isEmpty()) {
            dne.setRua(dne.getRua().replace(" ", "%"));
        }

        Cidade cidade = dne.getCidade();
        Bairro bairro = dne.getBairro();

        if ((cidade != null)) {
            if (cidade.getId() != null) {
                cidade = cityService.find(cidade.getId());
                if ((cidade.getNome() != null) && (!cidade.getNome().equals(""))) {
                    sql += "JOIN d.cidade c ";
                }
            }
        }
        if (bairro != null) {
            if (bairro.getId() != null) {
                bairro = bairroService.find(bairro.getId());
                if ((bairro.getNome() != null) && (!bairro.getNome().equals(""))) {
                    sql += "JOIN d.bairro b ";
                }
            }
        }

        sql += " WHERE ";

        if (dne.getCep() != null && !dne.getCep().isEmpty()) {
            sql += " lower(d.cep) like lower(:cep) and ";
        }
        if (dne.getRua() != null && !dne.getRua().isEmpty()) {
            sql += " lower(d.rua) like lower(:rua) and ";
        }
        if (cidade != null) {
            if (cidade.getNome() != null && !cidade.getNome().isEmpty()) {
                sql += " lower(c.nome) like lower(:nomeCidade) and ";
            }
        }
        if (bairro != null) {
            if (bairro.getNome() != null && !bairro.getNome().isEmpty()) {
                sql += " lower(b.nome) like lower(:nomeBairro) and ";
            }
        }

        sql += " d.ativo = true";

        Query query = getEntityManager().createQuery(select.concat(sql).concat(orderBy));

        setQuantidadeRegistros(sql, query, dne, cidade, bairro);

        setParameters(query, dne, cidade, bairro);

        if (first != null && pageSize != null) {
            query.setFirstResult(first).setMaxResults(pageSize);
        }

        return query.getResultList();
    }

    @Transient
    private void setParameters(Query query, Dne dne, Cidade cidade, Bairro bairro) {
        if (dne.getCep() != null && !dne.getCep().isEmpty()) {
            query.setParameter("cep", "%" + dne.getCep().trim().replaceAll(" ", "%") + "%");
        }

        if (dne.getRua() != null && !dne.getRua().isEmpty()) {
            query.setParameter("rua", "%" + dne.getRua().trim().replaceAll(" ", "%") + "%");
        }

        if (cidade != null) {
            if ((cidade.getNome() != null) && (!cidade.getNome().equals(""))) {
                query.setParameter("nomeCidade", "%" + "parnaíba" + "%");
            }
        }

        if (bairro != null) {
            if (bairro.getNome() != null && !bairro.getNome().isEmpty()) {
                query.setParameter("nomeBairro", "%" + bairro.getNome().trim().replaceAll(" ", "%") + "%");
            }
        }
    }

    private void setQuantidadeRegistros(String sql, Query query, Dne dne, Cidade cidade, Bairro bairro) {

        String select = "SELECT count(d) ";

        query = getEntityManager().createQuery(select + sql);

        setParameters(query, dne, cidade, bairro);

        quantidadeRegistrosResults = (Long) query.getSingleResult();
    }

    @Override
    public Long quantidadeRegistros() {
        return quantidadeRegistrosResults;
    }
}
